#!/bin/bash

print() {
  echo "    [PRECOMMIT]: $1" >&2
}

check_and_lint_docs() {
  local staged_files="$1"
  local docs_path="$2"
  local docs_name="$3"

  print "Checking for changes in $docs_name..."
  if echo "$staged_files" | grep "^$docs_path/" --silent; then
    print "Changes spotted. Running $docs_name docs lint..."
    try yarn workspace "$docs_name" lint
    print "Success."
  else
    print "No changes. Skipping $docs_name docs lint."
  fi
}

BRANCH=$(git symbolic-ref HEAD)
if [ "$BRANCH" = "refs/heads/main" ]; then
  print "You tried to commit to main, which is probably a mistake. Aborting commit."
  exit 1
fi

# `lint-staged` is great, but its' parsing capabilities of more advanced CLIs is poor.
# We can use it reliably only with programs that expect the following syntax:
#     command [options] [arg1] [arg2] [arg3] ...
# more sophisticated checks should be done in this script without `lint-staged`.
print 'Running "lint-staged" ...'
yarn lint-staged

LOGFILE=.husky/log.txt
try() {
  if ! "$@" >"$LOGFILE" 2>&1; then
    print "Errors detected. Aborting commit."
    print "Error logs:\n"
    cat "$LOGFILE"
    exit 1
  fi
}

# Some precommit checks can take several seconds. Therefore, we
# want them to trigger only when relevant files are staged.
STAGED_FILES=$(git diff-index HEAD --cached --name-only)

print "Checking for changes in Reanimated TypeScript source files..."
REANIMATED_PATH="packages/react-native-reanimated"
if echo "$STAGED_FILES" | grep "$REANIMATED_PATH/src/.*\.\(ts\|tsx\)$" --silent; then
  print "Changes spotted. Running TypeScript checks..."

  try yarn workspace react-native-reanimated type:check
  try yarn workspace react-native-reanimated find-unused-code:js

  print "Success."
else
  print "No changes. Skipping TypeScript checks."
fi

# Linting docs
for DOCS in docs-reanimated docs-worklets; do
  DOCS_PATH="docs/$DOCS"
  check_and_lint_docs "$STAGED_FILES" "$DOCS_PATH" "$DOCS"
done

# This automatically builds Worklets Babel plugin JavaScript files if their
# TypeScript counterparts were changed. It also adds the output file to the commit
# if the built file differs from currently staged one.
print "Checking for changes in Worklets Babel plugin source files..."
PLUGIN_PATH="packages/react-native-worklets/plugin"
if echo "$STAGED_FILES" | grep -E "$PLUGIN_PATH" >/dev/null; then
  print "Changes spotted. Building Worklets Babel plugin files..."

  yarn workspace babel-plugin-worklets build

  PLUGIN_OUTPUT_PATH="$PLUGIN_PATH/index.js"
  HAS_COMMITTED_CHANGES=false
  if git status -u | grep -E "$PLUGIN_OUTPUT_PATH" --silent; then
    git add "$PLUGIN_PATH"
    HAS_COMMITTED_CHANGES=true
  fi

  if [ "$HAS_COMMITTED_CHANGES" = true ]; then
    print "Non-committed changes were automatically added to the commit."
  else
    print "All Babel plugin files were already committed."
  fi
else
  print "No changes. Skipping plugin checks."
fi

print "All good, committing..."

exit 0
